import ujson as json

from coin.exchange.util.feed_checker import get_default_feed_checker_config

import coin.strategy.mm.fastfeature.util as ffutil
import coin.strategy.mm.fastfeature.fast_feature_feed_spec as fffspec
import coin.strategy.mm.fastfeature.feature_feed_converter as ffcv
import coin.strategy.mm.fastfeature.feed_manager as fmgr


def get_product_map(config_filename, start_time):
  configs = json.load(open(config_filename, 'r'))
  feature_config = json.load(open(configs['feature_filename'], 'r'))
  product_map = ffutil.product_map_from_symbol_dicts(feature_config['symbols'], start_time)
  targets = feature_config['targets']
  target_products = []
  for target in targets:
    for product, pproduct in product_map.items():
      if pproduct.symbol_string == target:
        target_products.append(product)
  return product_map, target_products


def create_linear_model(config_filename, start_time, track_queue=True):
  from pyfastfeature.feature.linear_model import LinearModel
  with open(config_filename, 'r') as config_file:
    configs = json.load(config_file)
    with open(configs['feature_filename'], 'r') as feature_file:
      feature_config = json.load(feature_file)
      product_map = ffutil.product_map_from_symbol_dicts(feature_config['symbols'], start_time)
      aggregation_map = ffutil.aggregation_map_from_symbol_dicts(feature_config['symbols'],
                                                                 start_time)
      return (LinearModel(product_map.values(),
                          config_filename=config_filename,
                          track_queue=track_queue),
              product_map,
              aggregation_map)


def create_linear_model2(config_filename, start_time, track_queue=True):
  from pyfastfeature.feature.linear_model import LinearModel
  with open(config_filename, 'r') as config_file:
    configs = json.load(config_file)
    with open(configs['feature_filename'], 'r') as feature_file:
      feature_config = json.load(feature_file)
      product_map, target_products = get_product_map(config_filename, start_time)
      aggregation_map = ffutil.aggregation_map_from_symbol_dicts(feature_config['symbols'],
                                                                 start_time)
      return (LinearModel(product_map.values(),
                          config_filename=config_filename,
                          track_queue=track_queue),
              product_map,
              aggregation_map,
              target_products)


def get_feed_spec(config_filename, start_time):
  return fffspec.from_file(config_filename, start_time)


def create_feed_converter(feed_convert_cls, product_map, feedspec, current_datetime):
  return feed_convert_cls(
      product_map,
      product_ticksize_map={
          product: fmgr.get_target_tick_size(product) for product in product_map.keys()
      },
      level_override_map=feedspec.level_override_map,
      bitmex_bbo_compress=feedspec.bitmex_bbo_compress,
      okex_trade_min_qty=feedspec.okex_trade_min_qty)


class FeatureDumperFactory(object):
  def __init__(self,
               feature_dumper_cls,
               config_filename,
               start_time,
               recorder_config_filename,
               force_fastfeed):
    configs = json.load(open(config_filename, 'r'))
    self.product_map = ffutil.product_map_from_symbol_dicts(configs['symbols'], start_time)
    self.aggregation_map = ffutil.aggregation_map_from_symbol_dicts(configs['symbols'], start_time)

    self.feedspec = fffspec.from_file(configs['feed_spec_path'], start_time)

    self.cant_use_fastfeed = False
    if not force_fastfeed:
      for product in list(self.product_map.keys()):
        if product.exchange in ["Gopax"]:
          self.cant_use_fastfeed = True

    if self.cant_use_fastfeed:
      feed_convert_cls = ffcv.FeatureArchiveFeedConverter
    else:
      feed_convert_cls = ffcv.FeatureFeedCacheConverter

    feed_converter = create_feed_converter(feed_convert_cls,
                                           self.product_map,
                                           self.feedspec,
                                           start_time)

    self.feed_checker_config = get_default_feed_checker_config(self.product_map.keys())

    self.feature_dumper = feature_dumper_cls(product_map=self.product_map,
                                             aggregation_map=self.aggregation_map,
                                             feedspec=self.feedspec,
                                             config_filename=config_filename,
                                             recorder_config_filename=recorder_config_filename,
                                             feed_converter=feed_converter)


class LmConverterFactory(object):
  def __init__(self, profile_path, product_map, start_time):
    splits = profile_path.split("/")
    splits[-1] = "feed_info.json"
    self.feedspec = fffspec.from_file("/".join(splits), start_time)
    self.product_map = product_map
    self.start_time = start_time

  def create_feed_converter(self, feed_convert_cls):
    return create_feed_converter(feed_convert_cls, self.product_map, self.feedspec, self.start_time)
